package mstparser;

import java.util.List;

/**
 *
 * @author Martin Haulrich
 */
public class DependencyDecoderLOP extends DependencyDecoder {

    /**
     * 
     * @param pipe
     */
    public DependencyDecoderLOP(DependencyPipe pipe) {
        super(pipe);
    }


    /**
     * Finds score for unlabelled edge.
     * @param i Index of dependent node.
     * @param j Index of governor node.
     * @param probs Array holding scores for all features-vectors related to unlabelled edges.
     * @return Score for the edge from i to j.
     */
    public static double getScore(int i, int j, double[][][] probs) {

        int small = Math.min(i, j);
        int large = Math.max(i, j);
        int dir = i < j ? 0 : 1;

        return probs[small][large][dir];
    }


    /**
     * Finds score for labelled edge (including the score for the unlabelled edge).
     * @param i Index of dependent node.
     * @param j Index of governor node.
     * @param type Dependency type.
     * @param probs Array holding scores for all features-vectors related to unlabelled edges.
     * @param labelled_probs Array holding scores for all features-vectors related to labelled edges.
     * @return Score for the edge from i to j.
     */
    public static double getScore(int i, int j, int type, double[][][] probs, double[][][][] labelled_probs) {
        if (labelled_probs == null) {
            return getScore(i, j, probs);
        }

        int small = Math.min(i, j);
        int large = Math.max(i, j);
        int dir = i < j ? 0 : 1;

        double unlabelled_score = probs[small][large][dir];

        double lab_sc1 = labelled_probs[i][type][dir][1];
        double lab_sc2 = labelled_probs[j][type][dir][0];

        return unlabelled_score + lab_sc1 + lab_sc2;
    }


    /**
     * Finds feature vector for unlabelled edge.
     * @param i Index of dependent node.
     * @param j Index of governor node.
     * @param probs Array holding all features-vectors related to unlabelled edges.
     * @return Feature vector for the edge from i to j.
     */
    private FeatureVector getFeatureVector(int i, int j, FeatureVector[][][] fvs) {

        int small = Math.min(i, j);
        int large = Math.max(i, j);
        int dir = i < j ? 0 : 1;

        return fvs[small][large][dir];
    }


    /**
     * Finds feature vector for labelled edge (including the feature vector for the unlabelled edge).
     * @param i Index of dependent node.
     * @param j Index of governor node.
     * @param type Dependency type.
     * @param fvs Array holding all features-vectors related to unlabelled edges.
     * @param labelled_fvs Array holding all features-vectors related to labelled edges.
     * @return Feature vector for the edge from i to j.
     */
    private FeatureVector getFeatureVector(int i, int j, int type, FeatureVector[][][] fvs, FeatureVector[][][][] labelled_fvs) {

        int small = Math.min(i, j);
        int large = Math.max(i, j);
        int dir = i < j ? 0 : 1;

        FeatureVector unlabelled_fv = fvs[small][large][dir];

        FeatureVector lab_fv1 = labelled_fvs[i][type][dir][1];
        FeatureVector lab_fv2 = labelled_fvs[j][type][dir][0];

        FeatureVector result = unlabelled_fv;
        result.cat(lab_fv1);
        result.cat(lab_fv2);

        return result;
    }


    /**
     * Find best K best non-projective parses of dependency instance.
     * @param inst Dependency instance to find best parses for.
     * @param fvs Array holding all features-vectors related to unlabelled edges.
     * @param probs Array holding scores for all features-vectors related to unlabelled edges.
     * @param nt_fvs Array holding all features-vectors related to labelled edges.
     * @param nt_probs Array holding scores for all features-vectors related to labelled edges.
     * @param K Upper limit for number of best parses to be found.
     * @return Two-dimensional array containing the result of the decoding. (See description below)
     * Description of return array:
     * First dimension is K-dimensional and contains an array containing two items for each K.
     * The first of these items contains a feature vector for the parse. This feature vector is a concatanation of the feature vectors for the edges in the parse.
     * The second item contains a string representation of the parse. Each edge in the parse is represented in the following form:
     *      'governorIndex|dependentIndex:dependecyTypeNumber '
     * all edges a concatanated into one string. dependencyType is '0' if the parse is unlabelled.
     * The trailing whitespace in the string is removed.
     * An example:
     * 2|1:2 0|2:8 2|3:1 2|4:10 2|5:9
     */
    @Override
    public Object[][] decodeNonProjective(DependencyInstance inst,
            FeatureVector[][][] fvs,
            double[][][] probs,
            FeatureVector[][][][] nt_fvs,
            double[][][][] nt_probs, int K) {


        for (int i = 0; i < inst.forms.length; i++) {
            for (int j = 0; j < inst.forms.length; j++) {
                if (j != i) {
                    for (int t = 0; t < pipe.types.length; t++) {
                        double score = getScore(i, j, t, probs, nt_probs);
                        System.err.println(i + "->" + j + "\t" + pipe.types[t] + "\t" + score);
                    }
                    System.err.println("");
                }
            }
        }


        Object[][] d = new Object[1][2];

        return d;
    }
}
